/*
 * Copyright (C) 2012 Serge Begger
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */


#include "netpower.h"

netpower::netpower(QObject *parent) :
    QObject(parent)
{
    devh = NULL;
    deviceStatus = "N/N";
    firstRead = true;
    firmvareVersion = 0;
    deviceOpen = init();
    if (deviceOpen) {
        readData();
    }
}

netpower::~netpower() {
    if (deviceOpen) {
        libusb_release_interface(devh, 0);
    }
    libusb_close(devh);
}

bool netpower::init()
{
    if (libusb_init(NULL) >= 0) {

        devh = libusb_open_device_with_vid_pid(NULL, VENDOR_ID, PRODUCT_ID);

        if (devh != NULL) {
            libusb_detach_kernel_driver(devh, INTERFACE_NUMBER);
            if (libusb_claim_interface(devh, INTERFACE_NUMBER) >= 0)
                return true;
            else
                deviceStatus = "Interface error";
        } else {
            deviceStatus = "Unable to find the device";
            libusb_close(devh);
            libusb_exit(NULL);
        }
    } else
        deviceStatus = "Unable to initialize libusb";

    return false;
}

void netpower::readData()
{
    if (firstRead)
        readWriteData(0x36);
    else
        readWriteData(0x37);
}

void netpower::writeData()
{
    readWriteData(0x38);
}

void netpower::readWriteData(unsigned char command) {

    if (!deviceOpen)
        return;

    int bytes_received;
    int bytes_sent;
    int realy_bytes_received;
    int realy_bytes_sent;
    unsigned char data_in[64];
    unsigned char data_out[64];

    int i = 0;

    data_out[0] = command;
    for (i=0; i < 64; i++)
    {
        if (command == 0x37)
            data_out[i+1]=0x00;
        else{
            if (i <= OUT_VOLTAGE)
                data_out[i+1] = netpowerData[i];
        }
    }

    // Send data to the device.
    bytes_sent = libusb_interrupt_transfer(
                devh,
                0x01,
                data_out,
                sizeof(data_out),
                &realy_bytes_sent,
                TIMEOUT_MS);

    if (bytes_sent >= 0)
    {
        // Request data from the device.
        bytes_received = libusb_interrupt_transfer(
                    devh,
                    0x81,
                    data_in,
                    sizeof(data_in),
                    &realy_bytes_received,
                    TIMEOUT_MS);

        if (bytes_received >= 0)
        {
            if (firstRead) {
                firstRead = false;
                firmvareVersion = data_in[1];
            } else {
                for (i = 0; i <= OUT_VOLTAGE; ++i)
                    netpowerData[i] = data_in[i+1];

                switch ((int)data_in[DEVICE_STATUS+1])
                {
                case IDLE_STATE: deviceStatus             = "IDLE"; break;
                case ACC_ON_DELAY_STATE: deviceStatus     = "ACC ON DELAY"; break;
                case PC_ON_DELAY_STATE: deviceStatus     = "PC ON DELAY"; break;
                case OS_LOAD_TIME_STATE: deviceStatus     = "OS LOAD TIME"; break;
                case PC_ON_STATE: deviceStatus            = "PC ON"; break;
                case PC_SHUTDOWN_STATE: deviceStatus      = "PC SHUTDOWN"; break;
                case OS_SHUTDOWN_TIME_STATE: deviceStatus = "OS SHUTDOWN TIME"; break;
                case ACC_OFF_DELAY_STATE: deviceStatus    = "ACC OFF DELAY"; break;
                case AKB_OFF_DELAY_STATE: deviceStatus    = "AKB OFF DELAY"; break;
                case CHECK_PC_ON_DELAY_STATE: deviceStatus ="CHECK PC ON DELAY STATE"; break;
                case R_OUT_DELAY_STATE: deviceStatus      = "R OUT DELAY STATE"; break;
                case SLEEP_STATE: deviceStatus            = "SLEEP STATE"; break;
                default: deviceStatus = "N/N"; break;
                }
            }
        } else {
            deviceStatus = "Error receiving data";
            deviceOpen = false;
        }
    }
    else
    {
        deviceStatus = "Error sending data";
        deviceOpen = false;
    }    
    if (!deviceOpen) {
        for (i = 0; i <= OUT_VOLTAGE; ++i)
            netpowerData[i] = 0;
    }
}
